package com.nickstumpos.android.GmailWidgetPlus.service;

import java.util.HashMap;
import java.util.Map;

import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.util.Log;

import com.nickstumpos.android.GmailWidgetPlus.Constants.GMWP_Constants;
import com.nickstumpos.android.GmailWidgetPlus.gmailProvider.GmailProvider;
import com.nickstumpos.android.GmailWidgetPlus.labels.LabelBlackListManager;
import com.nickstumpos.android.GmailWidgetPlus.widget.presentation.managers.WidgetManagerFactory;
import com.nickstumpos.android.GmailWidgetPlus.widget.presentation.managers.WidgetUIManager;
import com.nickstumpos.android.GmailWidgetPlus.widget.sizes.WidgetSize;

public class GmailWidgetService extends Service {

	private Map<String, GmailProvider>		providerReg		= null;
	private Map<String, Integer>			providerCount	= null;
	private Map<Integer, WidgetUIManager>	wmReg			= null;
	SharedPreferences						prefs			= null;

	public GmailWidgetService() {

		super();
	}

	private GmailProvider gmailProviderByAccount(final String account,
			final int widgetId,
			final WidgetSize size) {

		GmailProvider ret = null;
		String action = null;
		if (size != null) {
			switch (size) {
				case FOURxTWO:
					action = GMWP_Constants.ACTION_GWID_UPDATE_FBT;
					break;
				case TWOxTWO:
					action = GMWP_Constants.ACTION_GWID_UPDATE_TBT;
					break;
				default:
					action = GMWP_Constants.ACTION_GWID_UPDATE_TBT;
			}
		}
		if (this.providerReg == null) {
			this.providerReg = new HashMap<String, GmailProvider>();
		}
		if (account != null) {
			if (this.providerReg.get(account) == null) {
				this.providerReg.put(account,
						new GmailProvider(this.getApplicationContext(),
								account,
								this.retrieveShowAll(widgetId),
								action));
				this.providerReg.get(account).registerObserver();
			}
			ret = this.providerReg.get(account);
		}
		return ret;
	}

	private void handleCommand(final Intent intent) {

		this.initialSetup(intent);
		final String widgetAction = intent.getExtras()
				.getString(GMWP_Constants.EXTRA_WIDGET_ACTION);
		Log.i("GMWP", "Executing Command: " + widgetAction);
		if (GMWP_Constants.WIDGET_DN.equals(widgetAction)) {
			this.handleMoveDown(intent);
		} else if (GMWP_Constants.WIDGET_UP.equals(widgetAction)) {
			this.handleMoveUp(intent);
		} else if (GMWP_Constants.WIDGET_RMV_WIDGET.equals(widgetAction)) {
			this.handleRemoveWidget(intent);
		} else if (GMWP_Constants.WIDGET_NEW_WIDGET.equals(widgetAction)) {
			this.handleNewWidget(intent);
		} else if (GMWP_Constants.WIDGET_GMAIL_UPDATE.equals(widgetAction)) {
			this.handleGmailUpdate(intent);
		} else if (GMWP_Constants.WIDGET_SYSTEM_UPDATE.equals(widgetAction)) {
			this.handleSystemUpdate(intent);
		} else {
			Log.w("GMWP", "Invalid command " + widgetAction
					+ " for widget id: "
					+ this.retrieveWidgetID(intent));
		}
	}

	private void handleGmailUpdate(final Intent intent) {

		if (this.wmReg != null) {
			GmailProvider provider;
			final WidgetSize size = this.retrieveWidgetSize(intent);
			if (size != null) {
				for (final int widgetId : this.wmReg.keySet()) {
					final String account = this.prefs.getString(GMWP_Constants.PREF_ACCOUNT_REF + widgetId,
							null);
					provider = this.gmailProviderByAccount(account,
							widgetId,
							size);
					this.wmReg.get(widgetId)
							.updateWidget(provider.getLabelsAndCounts(widgetId),
									provider.getTotalUnread(),
									provider.haveAccount());
				}
			}
		}
	}

	private void handleMoveDown(final Intent intent) {

		final int id = this.retrieveWidgetID(intent);
		final WidgetSize size = this.retrieveWidgetSize(intent);
		if ((id != AppWidgetManager.INVALID_APPWIDGET_ID) && (size != null)) {
			final String account = this.prefs.getString(GMWP_Constants.PREF_ACCOUNT_REF + id,
					null);
			this.widgetManagerById(id, account, size).nextLabelSet();
		}
	}

	private void handleMoveUp(final Intent intent) {

		final int id = this.retrieveWidgetID(intent);
		final WidgetSize size = this.retrieveWidgetSize(intent);
		if ((id != AppWidgetManager.INVALID_APPWIDGET_ID) && (size != null)) {
			final String account = this.prefs.getString(GMWP_Constants.PREF_ACCOUNT_REF + id,
					null);
			this.widgetManagerById(id, account, size).previousLabelSet();
		}
	}

	private void handleNewWidget(final Intent intent) {

		final int id = this.retrieveWidgetID(intent);
		if (id != AppWidgetManager.INVALID_APPWIDGET_ID) {
			final String account = this.prefs.getString(GMWP_Constants.PREF_ACCOUNT_REF + id,
					null);
			final WidgetSize size = this.retrieveWidgetSize(intent);
			if ((account != null) && (size != null)) {
				if (this.providerCount == null) {
					this.providerCount = new HashMap<String, Integer>();
				}
				if (this.providerCount.containsKey(account)) {
					this.providerCount.put(account,
							this.providerCount.get(account) + 1);
				} else {
					this.providerCount.put(account, 1);
				}
				this.updateWidget(false, id, size);
			}
		}
	}

	private void handleRemoveWidget(final Intent intent) {

		final int id = this.retrieveWidgetID(intent);
		final WidgetSize size = this.retrieveWidgetSize(intent);
		if ((id != AppWidgetManager.INVALID_APPWIDGET_ID) && (size != null)) {
			final String account = this.prefs.getString(GMWP_Constants.PREF_ACCOUNT_REF + id,
					null);
			if (this.wmReg != null) {
				this.wmReg.remove(id);
			}
			if ((this.providerCount != null) && (account != null)) {
				if (this.providerCount.containsKey(account)) {
					this.providerCount.put(account,
							this.providerCount.get(account) - 1);
					if (this.providerCount.get(account) < 1) {
						this.providerReg.remove(account);
					}
				}
			}
			final SharedPreferences.Editor ed = this.prefs.edit();
			ed.remove(GMWP_Constants.PREF_ACCOUNT_REF + id);
			ed.remove(GMWP_Constants.PREF_SHOWALL_REF + id);
			ed.remove(GMWP_Constants.WIDGET_SKIN + id);
			ed.commit();
		}
	}

	private void handleSystemUpdate(final Intent intent) {

		final int[] ids = this.retrieveWidgetIDS(intent);
		final int id = this.retrieveWidgetID(intent);
		final WidgetSize size = this.retrieveWidgetSize(intent);
		boolean sync = true;
		if (size != null) {
			if (ids.length > 0) {
				for (final int i : ids) {
					this.updateWidget(sync, i, size);
					sync = false;
				}
			} else {
				if (id != AppWidgetManager.INVALID_APPWIDGET_ID) {
					this.updateWidget(sync, id, size);
				}
			}
		}
	}

	private void initialSetup(final Intent intent) {

		if (this.prefs == null) {
			this.prefs = this.getSharedPreferences(GMWP_Constants.GMW_PREFS_REF,
					0);
		}
		final int id = this.retrieveWidgetID(intent);
		if ((id != AppWidgetManager.INVALID_APPWIDGET_ID) && !LabelBlackListManager.isInit(id)) {
			LabelBlackListManager.initBlacklist(this, id);
		}
	}

	@Override
	public IBinder onBind(final Intent arg0) {

		return null;
	}

	@Override
	public void onDestroy() {

		super.onDestroy();
		if (this.providerReg != null) {
			for (final String i : this.providerReg.keySet()) {
				this.providerReg.get(i).removeObserver();
			}
			this.providerReg.clear();
			this.providerReg = null;
		}
		if (this.providerCount != null) {
			this.providerCount.clear();
			this.providerCount = null;
		}
		if (this.wmReg != null) {
			this.wmReg.clear();
			this.wmReg = null;
		}
	}

	@Override
	public void onStart(final Intent intent, final int startId) {

		if ((intent != null) && intent.hasExtra(GMWP_Constants.EXTRA_WIDGET_ACTION)) {
			this.handleCommand(intent);
		}
	}

	@Override
	public int onStartCommand(final Intent intent,
			final int flags,
			final int startId) {

		if ((intent != null) && intent.hasExtra(GMWP_Constants.EXTRA_WIDGET_ACTION)) {
			this.handleCommand(intent);
		}
		return Service.START_STICKY;
	}

	private boolean retrieveShowAll(final int widgetId) {

		return this.prefs.getBoolean(GMWP_Constants.PREF_SHOWALL_REF + widgetId,
				false);
	}

	private int retrieveWidgetID(final Intent intent) {

		int ret = AppWidgetManager.INVALID_APPWIDGET_ID;
		if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
			ret = intent.getExtras()
					.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
		} else {
			final int[] ids = this.retrieveWidgetIDS(intent);
			if (ids.length > 0) {
				ret = ids[0];
			}
		}
		return ret;
	}

	private int[] retrieveWidgetIDS(final Intent intent) {

		int[] ret = {};
		if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS)) {
			ret = intent.getExtras()
					.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
		}
		return ret;
	}

	private WidgetSize retrieveWidgetSize(final Intent intent) {

		WidgetSize ret = null;
		if (intent.hasExtra(GMWP_Constants.EXTRA_WIDGET_SIZE)) {
			ret = WidgetSize.valueOf(intent.getExtras()
					.getString(GMWP_Constants.EXTRA_WIDGET_SIZE));
		}
		return ret;
	}

	private void updateWidget(final boolean sync,
			final int id,
			final WidgetSize size) {

		final String account = this.prefs.getString(GMWP_Constants.PREF_ACCOUNT_REF + id,
				null);
		final GmailProvider provider = this.gmailProviderByAccount(account,
				id,
				size);
		if (account != null) {
			if (sync) {
				provider.syncGmail();
			}
			this.widgetManagerById(id, account, size)
					.updateWidget(provider.getLabelsAndCounts(id),
							provider.getTotalUnread(),
							provider.haveAccount());
		}
	}

	private WidgetUIManager widgetManagerById(final int widgetId,
			final String account,
			final WidgetSize size) {

		if (this.wmReg == null) {
			this.wmReg = new HashMap<Integer, WidgetUIManager>();
		}
		if (!this.wmReg.containsKey(widgetId)) {
			this.wmReg.put(widgetId,
					WidgetManagerFactory.getWidgetUIManager(this.getApplicationContext(),
							widgetId,
							account,
							size));
		}
		return this.wmReg.get(widgetId);
	}
}
